#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using System.Collections; using System.Globalization; using System.IO; using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities; namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters { /// <summary> /// Parameters for the Skein hash function - a series of byte[] strings identified by integer tags. /// </summary> /// <remarks> /// Parameterised Skein can be used for: /// <ul> /// <li>MAC generation, by providing a <see cref="SkeinParameters.Builder.SetKey(byte[])">key</see>.</li> /// <li>Randomised hashing, by providing a <see cref="SkeinParameters.Builder.SetNonce(byte[])">nonce</see>.</li> /// <li>A hash function for digital signatures, associating a /// <see cref="SkeinParameters.Builder.SetPublicKey(byte[])">public key</see> with the message digest.</li> /// <li>A key derivation function, by providing a /// <see cref="SkeinParameters.Builder.SetKeyIdentifier(byte[])">key identifier</see>.</li> /// <li>Personalised hashing, by providing a /// <see cref="SkeinParameters.Builder.SetPersonalisation(DateTime,string,string)">recommended format</see> or /// <see cref="SkeinParameters.Builder.SetPersonalisation(byte[])">arbitrary</see> personalisation string.</li> /// </ul> /// </remarks> /// <seealso cref="BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests.SkeinEngine"/> /// <seealso cref="BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests.SkeinDigest"/> /// <seealso cref="BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs.SkeinMac"/> public class SkeinParameters : ICipherParameters { /// <summary> /// The parameter type for a secret key, supporting MAC or KDF functions: 0 /// </summary> public const int PARAM_TYPE_KEY = 0; /// <summary> /// The parameter type for the Skein configuration block: 4 /// </summary> public const int PARAM_TYPE_CONFIG = 4; /// <summary> /// The parameter type for a personalisation string: 8 /// </summary> public const int PARAM_TYPE_PERSONALISATION = 8; /// <summary> /// The parameter type for a public key: 12 /// </summary> public const int PARAM_TYPE_PUBLIC_KEY = 12; /// <summary> /// The parameter type for a key identifier string: 16 /// </summary> public const int PARAM_TYPE_KEY_IDENTIFIER = 16; /// <summary> /// The parameter type for a nonce: 20 /// </summary> public const int PARAM_TYPE_NONCE = 20; /// <summary> /// The parameter type for the message: 48 /// </summary> public const int PARAM_TYPE_MESSAGE = 48; /// <summary> /// The parameter type for the output transformation: 63 /// </summary> public const int PARAM_TYPE_OUTPUT = 63; private IDictionary parameters; public SkeinParameters() : this(BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable()) { } private SkeinParameters(IDictionary parameters) { this.parameters = parameters; } /// <summary> /// Obtains a map of type (int) to value (byte[]) for the parameters tracked in this object. /// </summary> public IDictionary GetParameters() { return parameters; } /// <summary> /// Obtains the value of the <see cref="PARAM_TYPE_KEY">key parameter</see>, or <code>null</code> if not /// set. /// </summary> /// <returns>The key.</returns> public byte[] GetKey() { return (byte[])parameters[PARAM_TYPE_KEY]; } /// <summary> /// Obtains the value of the <see cref="PARAM_TYPE_PERSONALISATION">personalisation parameter</see>, or /// <code>null</code> if not set. /// </summary> public byte[] GetPersonalisation() { return (byte[])parameters[PARAM_TYPE_PERSONALISATION]; } /// <summary> /// Obtains the value of the <see cref="PARAM_TYPE_PUBLIC_KEY">public key parameter</see>, or /// <code>null</code> if not set. /// </summary> public byte[] GetPublicKey() { return (byte[])parameters[PARAM_TYPE_PUBLIC_KEY]; } /// <summary> /// Obtains the value of the <see cref="PARAM_TYPE_KEY_IDENTIFIER">key identifier parameter</see>, or /// <code>null</code> if not set. /// </summary> public byte[] GetKeyIdentifier() { return (byte[])parameters[PARAM_TYPE_KEY_IDENTIFIER]; } /// <summary> /// Obtains the value of the <see cref="PARAM_TYPE_NONCE">nonce parameter</see>, or <code>null</code> if /// not set. /// </summary> public byte[] GetNonce() { return (byte[])parameters[PARAM_TYPE_NONCE]; } /// <summary> /// A builder for <see cref="SkeinParameters"/>. /// </summary> public class Builder { private IDictionary parameters = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable(); public Builder() { } public Builder(IDictionary paramsMap) { IEnumerator keys = paramsMap.Keys.GetEnumerator(); while (keys.MoveNext()) { int key = (int)keys.Current; parameters.Add(key, paramsMap[key]); } } public Builder(SkeinParameters parameters) { IEnumerator keys = parameters.parameters.Keys.GetEnumerator(); while (keys.MoveNext()) { int key = (int)keys.Current; this.parameters.Add(key, parameters.parameters[key]); } } /// <summary> /// Sets a parameters to apply to the Skein hash function. /// </summary> /// <remarks> /// Parameter types must be in the range 0,5..62, and cannot use the value 48 /// (reserved for message body). /// <p/> /// Parameters with type < 48 are processed before /// the message content, parameters with type > 48 /// are processed after the message and prior to output. /// </remarks> /// <param name="type">the type of the parameter, in the range 5..62.</param> /// <param name="value">the byte sequence of the parameter.</param> public Builder Set(int type, byte[] value) { if (value == null) { throw new ArgumentException("Parameter value must not be null."); } if ((type != PARAM_TYPE_KEY) && (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE)) { throw new ArgumentException("Parameter types must be in the range 0,5..47,49..62."); } if (type == PARAM_TYPE_CONFIG) { throw new ArgumentException("Parameter type " + PARAM_TYPE_CONFIG + " is reserved for internal use."); } this.parameters.Add(type, value); return this; } /// <summary> /// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY"/> parameter. /// </summary> public Builder SetKey(byte[] key) { return Set(PARAM_TYPE_KEY, key); } /// <summary> /// Sets the <see cref="SkeinParameters.PARAM_TYPE_PERSONALISATION"/> parameter. /// </summary> public Builder SetPersonalisation(byte[] personalisation) { return Set(PARAM_TYPE_PERSONALISATION, personalisation); } /// <summary> /// Implements the recommended personalisation format for Skein defined in Section 4.11 of /// the Skein 1.3 specification. /// </summary> /// <remarks> /// The format is <code>YYYYMMDD email@address distinguisher</code>, encoded to a byte /// sequence using UTF-8 encoding. /// </remarks> /// <param name="date">the date the personalised application of the Skein was defined.</param> /// <param name="emailAddress">the email address of the creation of the personalised application.</param> /// <param name="distinguisher">an arbitrary personalisation string distinguishing the application.</param> public Builder SetPersonalisation(DateTime date, string emailAddress, string distinguisher) { try { MemoryStream bout = new MemoryStream(); StreamWriter outBytes = new StreamWriter(bout, System.Text.Encoding.UTF8); outBytes.Write(date.ToString("YYYYMMDD", CultureInfo.InvariantCulture)); outBytes.Write(" "); outBytes.Write(emailAddress); outBytes.Write(" "); outBytes.Write(distinguisher); BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(outBytes); return Set(PARAM_TYPE_PERSONALISATION, bout.ToArray()); } catch (IOException e) { throw new InvalidOperationException("Byte I/O failed.", e); } } /// <summary> /// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter. /// </summary> public Builder SetPublicKey(byte[] publicKey) { return Set(PARAM_TYPE_PUBLIC_KEY, publicKey); } /// <summary> /// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter. /// </summary> public Builder SetKeyIdentifier(byte[] keyIdentifier) { return Set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier); } /// <summary> /// Sets the <see cref="SkeinParameters.PARAM_TYPE_NONCE"/> parameter. /// </summary> public Builder SetNonce(byte[] nonce) { return Set(PARAM_TYPE_NONCE, nonce); } /// <summary> /// Constructs a new <see cref="SkeinParameters"/> instance with the parameters provided to this /// builder. /// </summary> public SkeinParameters Build() { return new SkeinParameters(parameters); } } } } #pragma warning restore #endif